/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package be.ugent.medirem.persistence.facade;

import be.ugent.medirem.persistence.entity.Account;
import be.ugent.medirem.persistence.entity.GeneralPractitioner;
import be.ugent.medirem.persistence.entity.Location;
import be.ugent.medirem.persistence.entity.Patient;
import be.ugent.medirem.persistence.entity.details.GpDetails;
import be.ugent.medirem.persistence.entity.details.LocationDetails;
import be.ugent.medirem.persistence.entity.details.PatientDetails;
import be.ugent.medirem.persistence.entity.values.PatientValues;
import be.ugent.medirem.persistence.exception.EntityNotFoundException;
import be.ugent.medirem.persistence.util.EntityDetailsToEntity;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Thomas Roelens 
 */
@Stateless
public class PatientDaoBean implements PatientDaoLocal {

    @PersistenceContext
    private EntityManager em;

    public Long create(String username, String password, String socialsecuritynr) {
        Patient newPatient = new Patient();
        newPatient.setUsername(username);
        newPatient.setPassword(password);
        newPatient.setSocialSecurityNr(socialsecuritynr);

        try {
            persist(newPatient);
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return newPatient.getId();
    }

    public Long create(PatientValues values) {
        Patient newPatient = new Patient();
        newPatient.setUsername(values.getUsername());
        newPatient.setPassword(values.getPassword());
        newPatient.setSocialSecurityNr(values.getSocialSecurityNumber());
        newPatient.setBirthdate(values.getBirthDate());
        newPatient.setBloodgroup(values.getBloodgroup());
        newPatient.setFirstname(values.getFirstname());
        newPatient.setSurname(values.getSurname());

        try {
            persist(newPatient);
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return newPatient.getId();
    }

    public PatientDetails getDetails(Long patientId) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;
        PatientDetails details = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                details = new PatientDetails(patient.getId(), patient.getUsername(),
                        patient.getFirstname(), patient.getSurname(), patient.getBirthdate(),
                        patient.getBloodgroup(), patient.getSocialSecurityNr(), patient.getLocation() == null ? null : patient.getLocation().getId());
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return details;
    }

    public LocationDetails getLocationDetails(Long patientId) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;
        Location location = null;
        LocationDetails details = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        try {
            patient = em.find(Patient.class, patientId);
            location = patient.getLocation();


            if (patient == null) {
                throw new EntityNotFoundException();
            } else if (location == null) {
                return null;
            } else {
                details = new LocationDetails(location.getId(), location.getStreet(), location.getNumber(),
                        location.getZipcode(), location.getTown(), location.getCountry(),
                        location.getPhonenr(), location.getEmail());
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return details;
    }

    public List<PatientDetails> getAllPatients() {
        List<PatientDetails> details = new ArrayList<PatientDetails>();

        // TODO: try catch nodig?
        List<Patient> patients = em.createNamedQuery("Patient.FindAll").getResultList();
        for (Patient p : patients) {
            details.add(new PatientDetails(p.getId(), p.getUsername(),
                    p.getFirstname(), p.getSurname(), p.getBirthdate(),
                    p.getBloodgroup(), p.getSocialSecurityNr(), p.getLocation() != null ? p.getLocation().getId() : null));
        }

        return details;
    }

    public void remove(Long patientId) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                patient = em.merge(patient);
                em.remove(patient);
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

    public void update(PatientValues details) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;

        if (details.getId() == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        try {
            patient = em.find(Patient.class, details.getId());

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                if (details.getFirstname() != null) {
                    patient.setFirstname(details.getFirstname());
                }
                if (details.getSurname() != null) {
                    patient.setSurname(details.getSurname());
                }
                if (details.getSocialSecurityNumber() != null) {
                    patient.setSocialSecurityNr(details.getSocialSecurityNumber());
                }
                if (details.getBirthDate() != null) {
                    patient.setBirthdate(details.getBirthDate());
                }
                if (details.getBloodgroup() != null) {
                    patient.setBloodgroup(details.getBloodgroup());
                }
                if (details.getUsername() != null) {
                    patient.setUsername(details.getUsername());
                }
                if (details.getLocationId() != null) {
                    Location newLocation = em.find(Location.class, details.getLocationId());
                    patient.setLocation(newLocation);
                }
                em.merge(patient);
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

    }

    public void update(Long patientId, Long locationId) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        if (locationId == null) {
            throw new IllegalArgumentException("Location id is null");
        }
        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                Location l = em.find(Location.class, locationId);

                patient.setLocation(l);

                em.merge(patient);
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

    public void updatePassword(Long patientId, String oldPassword, String newPassword) throws EntityNotFoundException, IllegalArgumentException {
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        } else if (oldPassword == null || newPassword == null) {
            throw new IllegalArgumentException("Patient password is null");
        }
        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                if (Account.encryptPwd(oldPassword).equals(patient.getPassword())) {
                    patient.setPassword(newPassword);
                    em.merge(patient);
                } else {
                    throw new IllegalArgumentException("Old password does not match");
                }
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

    public List<GpDetails> getGpPublicDetails(Long patientId) {
        Patient patient = null;
        List<GpDetails> gpList = new ArrayList<GpDetails>();

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                for (GeneralPractitioner gp : patient.getGeneralPractitioners()) {
                    gpList.add(EntityDetailsToEntity.gPToDetails(gp));
                }
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return gpList;
    }

    public Long getPatientId(String username) throws IllegalArgumentException {
        Long id = null;
        try {
            id = (Long) em.createNamedQuery("Patient.GetId").setParameter("username", username).getSingleResult();
        } catch (Exception ex) {
            throw new IllegalArgumentException("Username not found: " + username);
        }
        return id;
    }

    public void persist(Object object) {
        em.persist(object);
    }

    public PatientDetails searchPatientsBySocialSecurityNumber(String number) {
        PatientDetails patient = null;
        try {
            Patient p = (Patient) em.createNamedQuery("Patient.FindBySocialSecurityNumber").setParameter("number", number).getSingleResult();
            patient = new PatientDetails(p.getUsername(), p.getSocialSecurityNr());
            patient.setBirthDate(p.getBirthdate());
            patient.setBloodgroup(p.getBloodgroup());
            patient.setFirstname(p.getFirstname());
            patient.setSurname(p.getSurname());
            patient.setPatientId(p.getId());
            patient.setLocationId(p.getLocation().getId());
        } catch (Exception e) {
        }
        return patient;
    }
}
